package edu.unf.cen6940.dao;

import edu.unf.cen6940.domain.Student;

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.skyway.spring.util.dao.AbstractJpaDao;

import org.springframework.dao.DataAccessException;

import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Repository;

import org.springframework.transaction.annotation.Transactional;

/**
 * DAO to manage Student entities.
 * 
 */
@Repository("StudentDAO")
@Transactional
public class StudentDAOImpl extends AbstractJpaDao<Student> implements
		StudentDAO {

	/**
	 * Set of entity classes managed by this DAO.  Typically a DAO manages a single entity.
	 *
	 */
	private final static Set<Class<?>> dataTypes = new HashSet<Class<?>>(Arrays.asList(new Class<?>[] { Student.class }));

	/**
	 * EntityManager injected by Spring for persistence unit rms
	 *
	 */
	@PersistenceContext(unitName = "rms")
	private EntityManager entityManager;

	/**
	 * Instantiates a new StudentDAOImpl
	 *
	 */
	public StudentDAOImpl() {
		super();
	}

	/**
	 * Get the entity manager that manages persistence unit 
	 *
	 */
	public EntityManager getEntityManager() {
		return entityManager;
	}

	/**
	 * Returns the set of entity classes managed by this DAO.
	 *
	 */
	public Set<Class<?>> getTypes() {
		return dataTypes;
	}

	/**
	 * JPQL Query - findStudentByStudentId
	 *
	 */
	@Transactional
	public Student findStudentByStudentId(Integer studentId) throws DataAccessException {

		return findStudentByStudentId(studentId, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByStudentId
	 *
	 */

	@Transactional
	public Student findStudentByStudentId(Integer studentId, int startResult, int maxRows) throws DataAccessException {
		try {
			Query query = createNamedQuery("findStudentByStudentId", startResult, maxRows, studentId);
			return (edu.unf.cen6940.domain.Student) query.getSingleResult();
		} catch (NoResultException nre) {
			return null;
		}
	}

	/**
	 * JPQL Query - findStudentByCurrentPositionContaining
	 *
	 */
	@Transactional
	public Set<Student> findStudentByCurrentPositionContaining(String currentPosition) throws DataAccessException {

		return findStudentByCurrentPositionContaining(currentPosition, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByCurrentPositionContaining
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByCurrentPositionContaining(String currentPosition, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByCurrentPositionContaining", startResult, maxRows, currentPosition);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByYearGraduated
	 *
	 */
	@Transactional
	public Set<Student> findStudentByYearGraduated(Integer yearGraduated) throws DataAccessException {

		return findStudentByYearGraduated(yearGraduated, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByYearGraduated
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByYearGraduated(Integer yearGraduated, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByYearGraduated", startResult, maxRows, yearGraduated);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByEmail
	 *
	 */
	@Transactional
	public Set<Student> findStudentByEmail(String email) throws DataAccessException {

		return findStudentByEmail(email, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByEmail
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByEmail(String email, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByEmail", startResult, maxRows, email);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByNnumber
	 *
	 */
	@Transactional
	public Set<Student> findStudentByNnumber(String nnumber) throws DataAccessException {

		return findStudentByNnumber(nnumber, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByNnumber
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByNnumber(String nnumber, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByNnumber", startResult, maxRows, nnumber);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByGraduated
	 *
	 */
	@Transactional
	public Set<Student> findStudentByGraduated(String graduated) throws DataAccessException {

		return findStudentByGraduated(graduated, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByGraduated
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByGraduated(String graduated, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByGraduated", startResult, maxRows, graduated);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByFirstNameContaining
	 *
	 */
	@Transactional
	public Set<Student> findStudentByFirstNameContaining(String firstName) throws DataAccessException {

		return findStudentByFirstNameContaining(firstName, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByFirstNameContaining
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByFirstNameContaining(String firstName, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByFirstNameContaining", startResult, maxRows, firstName);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByPrimaryKey
	 *
	 */
	@Transactional
	public Student findStudentByPrimaryKey(Integer studentId) throws DataAccessException {

		return findStudentByPrimaryKey(studentId, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByPrimaryKey
	 *
	 */

	@Transactional
	public Student findStudentByPrimaryKey(Integer studentId, int startResult, int maxRows) throws DataAccessException {
		try {
			Query query = createNamedQuery("findStudentByPrimaryKey", startResult, maxRows, studentId);
			return (edu.unf.cen6940.domain.Student) query.getSingleResult();
		} catch (NoResultException nre) {
			return null;
		}
	}

	/**
	 * JPQL Query - findStudentByLastName
	 *
	 */
	@Transactional
	public Set<Student> findStudentByLastName(String lastName) throws DataAccessException {

		return findStudentByLastName(lastName, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByLastName
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByLastName(String lastName, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByLastName", startResult, maxRows, lastName);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByLastNameContaining
	 *
	 */
	@Transactional
	public Set<Student> findStudentByLastNameContaining(String lastName) throws DataAccessException {

		return findStudentByLastNameContaining(lastName, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByLastNameContaining
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByLastNameContaining(String lastName, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByLastNameContaining", startResult, maxRows, lastName);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByNnumberContaining
	 *
	 */
	@Transactional
	public Set<Student> findStudentByNnumberContaining(String nnumber) throws DataAccessException {

		return findStudentByNnumberContaining(nnumber, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByNnumberContaining
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByNnumberContaining(String nnumber, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByNnumberContaining", startResult, maxRows, nnumber);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findAllStudents
	 *
	 */
	@Secured("ROLE_ANONYMOUS")
	@Transactional
	public Set<Student> findAllStudents() throws DataAccessException {

		return findAllStudents(-1, -1);
	}

	/**
	 * JPQL Query - findAllStudents
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findAllStudents(int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findAllStudents", startResult, maxRows);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByCurrentPosition
	 *
	 */
	@Transactional
	public Set<Student> findStudentByCurrentPosition(String currentPosition) throws DataAccessException {

		return findStudentByCurrentPosition(currentPosition, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByCurrentPosition
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByCurrentPosition(String currentPosition, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByCurrentPosition", startResult, maxRows, currentPosition);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByMajorContaining
	 *
	 */
	@Transactional
	public Set<Student> findStudentByMajorContaining(String major) throws DataAccessException {

		return findStudentByMajorContaining(major, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByMajorContaining
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByMajorContaining(String major, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByMajorContaining", startResult, maxRows, major);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByFirstName
	 *
	 */
	@Transactional
	public Set<Student> findStudentByFirstName(String firstName) throws DataAccessException {

		return findStudentByFirstName(firstName, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByFirstName
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByFirstName(String firstName, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByFirstName", startResult, maxRows, firstName);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByMajor
	 *
	 */
	@Transactional
	public Set<Student> findStudentByMajor(String major) throws DataAccessException {

		return findStudentByMajor(major, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByMajor
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByMajor(String major, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByMajor", startResult, maxRows, major);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByGraduatedContaining
	 *
	 */
	@Transactional
	public Set<Student> findStudentByGraduatedContaining(String graduated) throws DataAccessException {

		return findStudentByGraduatedContaining(graduated, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByGraduatedContaining
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByGraduatedContaining(String graduated, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByGraduatedContaining", startResult, maxRows, graduated);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * JPQL Query - findStudentByEmailContaining
	 *
	 */
	@Transactional
	public Set<Student> findStudentByEmailContaining(String email) throws DataAccessException {

		return findStudentByEmailContaining(email, -1, -1);
	}

	/**
	 * JPQL Query - findStudentByEmailContaining
	 *
	 */

	@SuppressWarnings("unchecked")
	@Transactional
	public Set<Student> findStudentByEmailContaining(String email, int startResult, int maxRows) throws DataAccessException {
		Query query = createNamedQuery("findStudentByEmailContaining", startResult, maxRows, email);
		return new LinkedHashSet<Student>(query.getResultList());
	}

	/**
	 * Used to determine whether or not to merge the entity or persist the entity when calling Store
	 * @see store
	 * 
	 *
	 */
	public boolean canBeMerged(Student entity) {
		return true;
	}

	@Override
	public Set<Student> searchByTerm(String term) throws DataAccessException {
		Query query = createQuery("from Student myStudent where myStudent.firstName like ?1 or myStudent.lastName like ?1", -1, -1, "%"+term+"%");
		return new LinkedHashSet<Student>(query.getResultList());
	}
}
